home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DTP / DTP_TEX / 3239.ZIP / DVIMTP.ZIP / CHARPK.H < prev    next >
Text File  |  1987-10-21  |  11KB  |  345 lines

  1. /* -*-C-*- charpk.h */
  2. /*-->charpk*/
  3. /**********************************************************************/
  4. /******************************* charpk *******************************/
  5. /**********************************************************************/
  6.  
  7. /* This file departs from all others in the DVIxxx family in that it
  8. declares some private functions and globals which are required nowhere
  9. else.  Only charpk() is called from outside. */
  10.  
  11. BYTE get_bit();            /* return next bit from file */
  12. BYTE get_nybble();        /* return next 4-bit nybble from file */
  13. UNSIGN16 pk_packed_num();    /* get packed number from file */
  14.  
  15. BYTE bit_weight;        /* weight of current bit in next_byte */
  16. BYTE dyn_f;            /* dynamic packing flag */
  17. UNSIGN16 repeat_count;        /* how many times to repeat next row */
  18. BYTE next_byte;            /* current input byte */
  19. BYTE word_weight;        /* weight of current bit in *pword */
  20.  
  21. /**********************************************************************/
  22.  
  23. int
  24. charpk(c,outfcn)    /* return 0 on success, and EOF on failure */
  25. BYTE c;            /* current character value */
  26. void (*outfcn)();    /* (possibly NULL) function to output current row */
  27. {
  28.     INT16 count;        /* how many bits of current color left */
  29.     UNSIGN16 c_width;        /* character width in dots */
  30.     UNSIGN16 c_height;        /* character height in dots */
  31.     BOOLEAN do_output;        /* FALSE if outfcn is NULL */
  32.     register BYTE flag_byte;    /* current file flag byte */
  33.     UNSIGN16 h_bit;        /* horizontal position in row */
  34.     register UNSIGN16 i;    /* loop index */
  35.     register UNSIGN16 k;    /* loop index */
  36.     long offset;        /* offset into font file */
  37.     long p;            /* pointer into font file */
  38.     UNSIGN32 packet_length;    /* packet length */
  39.     UNSIGN32* pword;        /* pointer into img_row[] */
  40.     INT16 rows_left;        /* how many rows left */
  41.     struct char_entry *tcharptr;/* temporary char_entry pointer */
  42.     BYTE turn_on;        /* initial black/white flag */
  43.  
  44.     /*******************************************************************
  45.     This function is called to process a single character description in
  46.     the  PK  font  file.   The     character  packet  is  pointed  to   by
  47.     fontptr->ch[c].fontrp, and was set by readpk(), which moved past any
  48.     special commands that precede the packet.
  49.  
  50.     The PK  raster description  is encoded  in a  complex form,  but  is
  51.     guaranteed to step across raster rows  from left to right, and  down
  52.     from the  top  row  to  bottom  row,  such  that  in  references  to
  53.     image[n][m], m never decreases in a row, and n never increases in  a
  54.     character.  This means that we  only require enough memory space  to
  55.     hold one row, provided that outfcn(c,yoff) is called each time a row
  56.     is     completed.    This   is   an    important   economization    for
  57.     high-resolution output  devices --  e.g. a  10pt character  at  2400
  58.     dots/inch would require about  8Kb for the  entire image, but  fewer
  59.     than 25 bytes for a  single row.  A 72pt  character (such as in  the
  60.     aminch font) would need  about 430Kb for the  image, but only  about
  61.     200 bytes for a row.
  62.  
  63.     The code  follows  PKtoPX  quite closely,  particular  the  latter's
  64.     sections 37-43  for  preamble  processing, and  sections  44-51  for
  65.     raster decoding.
  66.  
  67.     Access to bit m in the current row is controlled through the  macros
  68.     SETBIT(m) and  TESTBIT(m) so  we  need not  be concerned  about  the
  69.     details of bit masking.  Too bad C does not have a bit data type!
  70.  
  71.     The row image is recorded in such a way that bits min_m .. max_m are
  72.     mapped onto  bits  0  ..  (max_m -  min_m)  in  img_row[],  so  that
  73.     outfcn(c,yoff) should be relieved of any shifting operations.
  74.  
  75.     outfcn(c,yoff) is NEVER called if either of hp or wp is <= 0, or  if
  76.     it is NULL.
  77.     *******************************************************************/
  78.  
  79.     if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c))
  80.     {
  81.     (void)warning(
  82.         "charpk():  Character value out of range for PK font file");
  83.     return(EOF);
  84.     }
  85.     tcharptr = &(fontptr->ch[c]);
  86.  
  87.     if (!VISIBLE(tcharptr))
  88.     return(0); /* empty character raster -- nothing to output */
  89.  
  90.     c_width = (UNSIGN16)tcharptr->wp;    /* local copies of these to save */
  91.     c_height = (UNSIGN16)tcharptr->hp;  /* pointer dereferencing in loops */
  92.  
  93.     p = (long)tcharptr->fontrp; /* font file raster pointer */
  94.     if (p < 0L)
  95.     {
  96.     (void)warning(
  97.         "charpk():  Requested character not found in PK font file");
  98.     return(EOF);
  99.     }
  100.     if (FSEEK(fontfp,p,0))
  101.     {
  102.     (void)warning(
  103.         "charpk():  FSEEK() failure for PK font file character raster");
  104.     return(EOF);
  105.     }
  106.  
  107.     /* Since readpk() has already done error checking on the file, and
  108.     recorded the character metrics, we need not repeat that work, and
  109.     concentrate instead on getting to the encoded raster description
  110.     which follows the character packet.  */
  111.  
  112.     img_words = (UNSIGN16)(c_width + 31) >> 5;
  113.     flag_byte = (BYTE)nosignex(fontfp,(BYTE)1); /* get packet flag byte */
  114.     dyn_f = flag_byte >> 4;    /* dyn_f is high 4 bits from flag_byte */
  115.     turn_on = (BYTE)(flag_byte & 0x08); /* turn_on is 8-bit from flag_byte */
  116.     flag_byte &= 0x07;        /* final flag_byte is low 3 bits */
  117.     do_output = (BOOLEAN)(outfcn != (void(*)())NULL);
  118.  
  119.     switch(flag_byte)        /* flag_byte is in 0..7 */
  120.     {
  121.     case 0:
  122.     case 1:
  123.     case 2:
  124.     case 3:        /* short character preamble */
  125.     packet_length = (UNSIGN32)flag_byte;
  126.     packet_length <<= 8;
  127.     packet_length += (UNSIGN32)nosignex(fontfp,(BYTE)1);
  128.     packet_length -= 8L;
  129.     offset = 9L;
  130.     break;
  131.  
  132.     case 4:
  133.     case 5:
  134.     case 6:        /* extended short character preamble */
  135.     packet_length = (UNSIGN32)(flag_byte & 0x03);
  136.     packet_length <<= 16;
  137.     packet_length += (UNSIGN32)nosignex(fontfp,(BYTE)2);
  138.     packet_length -= 13L;
  139.     offset = 14L;
  140.     break;
  141.  
  142.     case 7:        /* long character preamble */
  143.     packet_length = (UNSIGN32)nosignex(fontfp,(BYTE)4);
  144.     packet_length -= 28L;
  145.     offset = 32L;
  146.     break;
  147.  
  148.     } /* end switch */
  149.  
  150.     if (FSEEK(fontfp,offset,1)) /* position to start of raster data */
  151.     {
  152.     (void)warning(
  153.         "charpk():  FSEEK() failure for PK font file character raster");
  154.     return(EOF);
  155.     }
  156.  
  157.     bit_weight = 0;
  158.  
  159.     if (dyn_f == (BYTE)14)    /* <PKtoPX: Get raster by bits> */
  160.     {        /* uncompressed character image */
  161.     for (i = 0; i < c_height; ++i)
  162.     {
  163.         pword = img_row;
  164.         if (do_output)
  165.         (void)clrrow();
  166.         word_weight = (BYTE)31;
  167.         for (k = 0; k < c_width; ++k)
  168.         {
  169.         if (get_bit())
  170.             *pword |= power[word_weight];
  171.         if (word_weight)
  172.             --word_weight;
  173.         else
  174.         {
  175.             ++pword;
  176.             word_weight = (BYTE)31;
  177.         }
  178.         } /* end for (k) */
  179.         if (do_output)
  180.         (void)(*outfcn)(c,i);
  181.     } /* end for (i) */
  182.     }
  183.     else    /* <PKtoPX: Create normally packed raster> */
  184.     {    /* run-length encoded character image */
  185.     rows_left = (INT16)c_height;
  186.     h_bit = c_width;
  187.     repeat_count = 0;
  188.     word_weight = (BYTE)32;
  189.     pword = img_row;
  190.     if (do_output)
  191.         (void)clrrow();        /* clear img_row[] */
  192.     while (rows_left > 0)
  193.     {
  194.         count = (INT16)pk_packed_num();
  195.         while (count > 0)
  196.         {
  197.         if ( (count < (INT16)word_weight) && (count < (INT16)h_bit) )
  198.         {
  199.             if (turn_on)
  200.             {
  201.             *pword |= gpower[word_weight];
  202.             *pword &= ~gpower[word_weight - count];
  203.             }
  204.             h_bit -= (UNSIGN16)count;
  205.             word_weight -= (BYTE)count;
  206.             count = 0;
  207.         }
  208.         else if ( (count >= (INT16)h_bit) &&
  209.             (h_bit <= (UNSIGN16)word_weight) )
  210.         {
  211.             if (turn_on)
  212.             {
  213.             *pword |= gpower[word_weight];
  214.             *pword &= ~gpower[word_weight - h_bit];
  215.             }
  216.             if (do_output)
  217.             {
  218.             for (i = 0; i <= repeat_count; (--rows_left, ++i))
  219.                 (void)(*outfcn)(c,(UNSIGN16)(c_height-rows_left));
  220.             }
  221.             else
  222.             rows_left -= (INT16)(repeat_count + 1);
  223.             repeat_count = 0;
  224.             pword = img_row;
  225.             if (do_output)
  226.             (void)clrrow();
  227.             word_weight = (BYTE)32;
  228.             count -= (INT16)h_bit;
  229.             h_bit = c_width;
  230.         }
  231.         else
  232.         {
  233.             if (turn_on)
  234.             *pword |= gpower[word_weight];
  235.             pword++;
  236.             count -= (INT16)word_weight;
  237.             h_bit -= (UNSIGN16)word_weight;
  238.             word_weight = (BYTE)32;
  239.         }
  240.         } /* end while (count > 0) */
  241.         turn_on = (BYTE)(!turn_on);
  242.     } /* end while (rows_left > 0) */
  243.     if ((rows_left > 0) || (h_bit != c_width))
  244.     {
  245.         (void)warning(
  246.         "charpk():  Bad PK font file--more bits than required");
  247.         return(EOF);
  248.     }
  249.     } /* end if (run-length encoded image) */
  250.  
  251.     return(0);
  252. }
  253.  
  254. /*-->get_bit*/
  255. /**********************************************************************/
  256. /****************************** get_bit *******************************/
  257. /**********************************************************************/
  258.  
  259. BYTE
  260. get_bit()    /* return 0, or non-zero (not necessarily 1) */
  261. {
  262.     register BYTE temp;
  263.  
  264.     bit_weight >>= 1;
  265.     if (bit_weight == 0)    /* then must get new byte from font file */
  266.     {
  267.     next_byte = (BYTE)nosignex(fontfp,(BYTE)1);
  268.     bit_weight = (BYTE)128;
  269.     }
  270.     temp = next_byte & bit_weight;
  271.     next_byte &= ~bit_weight;    /* clear the just-read bit */
  272.  
  273.     return (temp);
  274. }
  275.  
  276.  
  277. /*-->get_nybble*/
  278. /**********************************************************************/
  279. /***************************** get_nybble *****************************/
  280. /**********************************************************************/
  281.  
  282. BYTE
  283. get_nybble()
  284. {
  285.     register BYTE temp;
  286.  
  287.     if (bit_weight == 0)    /* get high nybble */
  288.     {
  289.     next_byte = (BYTE)nosignex(fontfp,(BYTE)1);
  290.     temp = next_byte >> 4;
  291.     next_byte &= 0x0f;
  292.     bit_weight = (BYTE)1;
  293.     }
  294.     else    /* get low nybble */
  295.     {
  296.     temp = next_byte;    /* this has only 4 bits in it */
  297.     bit_weight = (BYTE)0;
  298.     }
  299.     return(temp);
  300. }
  301.  
  302. /*-->pk_packed_num*/
  303. /**********************************************************************/
  304. /*************************** pk_packed_num ****************************/
  305. /**********************************************************************/
  306.  
  307. UNSIGN16
  308. pk_packed_num() /* return a (non-negative) packed number from the font file */
  309. {    /* this function is recursive to one level only */
  310.     INT16 i,j;
  311.  
  312.     i = (INT16)get_nybble();
  313.     if (i == 0)
  314.     {
  315.     do
  316.     {
  317.         j = (INT16)get_nybble();
  318.         ++i;
  319.     } while (j == 0);
  320.     while (i > 0)
  321.     {
  322.         j <<= 4;
  323.         j += (INT16)get_nybble();
  324.         --i;
  325.     }
  326.     return((UNSIGN16)(j - 15 + ((13 - dyn_f) << 4) + dyn_f));
  327.     }
  328.     else if (i <= (INT16)dyn_f)
  329.     return((UNSIGN16)i);
  330.     else if (i < 14)
  331.     return((UNSIGN16)(((i - dyn_f - 1) << 4) + get_nybble() + dyn_f + 1));
  332.     else if (i == 14)
  333.     {
  334.     repeat_count = pk_packed_num();
  335.     return(pk_packed_num());
  336.     }
  337.     else
  338.     {
  339.     repeat_count = 1;
  340.     return(pk_packed_num());
  341.     }
  342. }
  343.  
  344.  
  345.